{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "# coding=gbk\n",
    "with open('data/apikey.txt', 'r', encoding='utf-8') as file:\n",
    "    api_key = file.read()\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "import pandas as pd\n",
    "import json\n",
    "data = pd.read_csv(\"data/智能诊断数据集.csv\")\n",
    "text = data['description']\n",
    "text = text.dropna()\n",
    "text_test = text.sample(n=10, random_state=42).copy()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-12-02T12:04:11.598018Z",
     "end_time": "2025-12-02T12:04:11.621619Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "prompt_0 = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"请分析一个疾病的介绍文字。我爬取了一些关于疾病的描述，现在需要你提取疾病的以下字段：病名，症状，人群，程度。其中，症状是描述疾病的特征或者发病原因。人群从**老人**，**年轻人**，**小孩**，**全年龄段**中选择，不要有其他选项，结果不带**。程度从**轻微**，**中等**，**严重**中选择，不要有其他选项。当你完成提取后，应当返回一个词典的格式，不输出其他结果。\"\n",
    "        ),\n",
    "        (\"human\", \"疾病介绍：{input}\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "prompt_1 = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"现在你是一个资深的医生，我会给你一段关于疾病的描述，你需要从这段文字中提取出以下字段：病名，症状，人群，程度。以下是每个字段的解释与要求：症状是描述疾病的特征或者发病原因，症状和病名只能从描述中提取，不可额外补充。人群从**老人**，**年轻人**，**小孩**，**全年龄段**中选择，不要有其他选项，结果不带**。程度从**轻微**，**中等**，**严重**中选择，不要有其他选项。当你完成提取后，应当返回一个词典的格式，不输出其他结果。\"\n",
    "        ),\n",
    "        (\"human\", \"疾病介绍：{input}\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "prompt_2 = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"请分析一个疾病的介绍文字。我爬取了一些关于疾病的描述，现在需要你提取疾病的以下字段：病名，症状，人群，程度。其中，人群从**老人**，**年轻人**，**小孩**，**全年龄段**中选择，不要有其他选项，结果不带**。程度从**轻微**，**中等**，**严重**中选择，不要有其他选项。当你完成提取后，应当返回一个词典的格式，不输出其他结果。以下是一个示例：“中暑是由于高温环境中发生的一组急性疾病。根据其主要发病机制和临床表现常分为三型：①热射病是因高温引起体温调节中枢功能障碍，热平衡失调使体内热蓄积，临床以高热、意识障碍、无汗为主要症状。由于头部受日光直接曝晒的...详细”：”病名“:中暑，”症状“：热射病、热平衡十条是体内热继续，临床以高热、意识障碍、无汗为主要症状，”人群“：全年龄段，”程度“：中等\"\n",
    "\n",
    "        ),\n",
    "        (\"human\", \"疾病介绍：{input}\"),\n",
    "    ]\n",
    ")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-12-02T12:04:12.120725Z",
     "end_time": "2025-12-02T12:04:12.131746Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "def parse_md_json(s: str):\n",
    "    if pd.isna(s):\n",
    "        return {}\n",
    "    # 去掉前后空格和代码围栏\n",
    "    s = s.strip().removeprefix('```json').removesuffix('```').strip()\n",
    "    try:\n",
    "        return json.loads(s)\n",
    "    except json.JSONDecodeError:\n",
    "        return {}\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-12-02T12:04:12.660846Z",
     "end_time": "2025-12-02T12:04:12.684432Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "result = pd.DataFrame(\n",
    "    {\n",
    "        'tempture':[],\n",
    "        'prompt':[],\n",
    "        '病名':[],\n",
    "        '症状':[],\n",
    "        '人群':[],\n",
    "        '程度':[]\n",
    "    }\n",
    ")\n",
    "\n",
    "temptures = ['0','0.5','1']\n",
    "prompts = [prompt_0,prompt_1,prompt_2]\n",
    "num = 0\n",
    "for prompt in prompts:\n",
    "    for tempture in temptures:\n",
    "        llm_0 = ChatOpenAI(\n",
    "        model=\"deepseek-ai/DeepSeek-V3\",\n",
    "        temperature=tempture,\n",
    "        openai_api_key=api_key,\n",
    "        openai_api_base=\"https://api.siliconflow.cn/v1\"\n",
    "    )\n",
    "        chain = prompt | llm_0\n",
    "\n",
    "        def analyze_description(input1):\n",
    "            ai_msg =chain.invoke(\n",
    "                {\n",
    "                    \"input\": input1,\n",
    "                }\n",
    "            )\n",
    "            return ai_msg.content\n",
    "\n",
    "        text_0 = text_test.apply(analyze_description)\n",
    "        text_1= pd.json_normalize(text_0.apply(parse_md_json))\n",
    "        text_1 = pd.DataFrame(text_1)\n",
    "        text_1['tempture'] = tempture\n",
    "        text_1['prompt'] = num\n",
    "        result = pd.concat([result,text_1],axis=0)\n",
    "    num += 1\n",
    "\n",
    "result.to_csv('data/extracted_data.csv',index=False)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-12-02T12:04:13.089742Z",
     "end_time": "2025-12-02T12:09:10.122881Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "'''\n",
    "------------------------------------------------------------------------------------------\n",
    "分界线，以下是大模型连接neo4j\n",
    "'''"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "\n",
    "#from langchain.chat_models import ChatOpenAI\n",
    "from langchain_openai import ChatOpenAI\n",
    "#from langchain_community.chat_models import ChatOpenAI\n",
    "from langchain_neo4j import GraphCypherQAChain\n",
    "from langchain_community.graphs import Neo4jGraph\n",
    "with open('data/apikey.txt', 'r', encoding='utf-8') as file:\n",
    "    api_key = file.read()\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "import pandas as pd\n",
    "import json"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T10:43:25.465649Z",
     "end_time": "2025-11-25T10:43:26.920290Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Node properties:\n",
      "Test {name: STRING, id: STRING}\n",
      "Employee {sal: INTEGER, name: STRING, id: INTEGER, deptno: INTEGER}\n",
      "Dept {deptno: INTEGER, location: STRING, dname: STRING}\n",
      "Customer {dob: STRING, name: STRING, id: INTEGER}\n",
      "CreditCard {number: STRING, cvv: STRING, expiredate: STRING, id: INTEGER}\n",
      "Name {name: STRING}\n",
      "alias {name: STRING}\n",
      "part {name: STRING}\n",
      "age {name: STRING}\n",
      "infection {name: STRING}\n",
      "insurance {name: STRING}\n",
      "department {name: STRING}\n",
      "check_list {name: STRING}\n",
      "symptom {name: STRING}\n",
      "complication {name: STRING}\n",
      "treatment {name: STRING}\n",
      "drug {name: STRING}\n",
      "period {name: STRING}\n",
      "rate {name: STRING}\n",
      "money {name: STRING}\n",
      "Movie {runtime: INTEGER, name: STRING}\n",
      "Actor {name: STRING}\n",
      "Relationship properties:\n",
      "\n",
      "The relationships:\n",
      "(:Name)-[:治疗费用]->(:money)\n",
      "(:Name)-[:别名]->(:alias)\n",
      "(:Name)-[:发病部位]->(:part)\n",
      "(:Name)-[:患病人群]->(:age)\n",
      "(:Name)-[:传染性]->(:infection)\n",
      "(:Name)-[:医疗报销]->(:insurance)\n",
      "(:Name)-[:治疗科室]->(:department)\n",
      "(:Name)-[:检查项目]->(:check_list)\n",
      "(:Name)-[:症状]->(:symptom)\n",
      "(:Name)-[:并发症]->(:complication)\n",
      "(:Name)-[:治疗方式]->(:treatment)\n",
      "(:Name)-[:治疗药物]->(:drug)\n",
      "(:Name)-[:治疗时长]->(:period)\n",
      "(:Name)-[:痊愈比例]->(:rate)\n",
      "(:Actor)-[:ACTED_IN]->(:Movie)\n"
     ]
    }
   ],
   "source": [
    "graph = Neo4jGraph(\n",
    "    url=\"bolt://localhost:7687\",\n",
    "    username=\"neo4j\",\n",
    "    password=\"123456789\"\n",
    ")\n",
    "print(graph.schema)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:09:40.429152Z",
     "end_time": "2025-11-25T11:09:43.314206Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(\n",
    "model=\"deepseek-ai/DeepSeek-V3\",\n",
    "temperature=0,\n",
    "openai_api_key=api_key,\n",
    "openai_api_base=\"https://api.siliconflow.cn/v1\"\n",
    ")\n",
    "\n",
    "chain = GraphCypherQAChain.from_llm(\n",
    "    llm, graph=graph, allow_dangerous_requests=True, verbose=True\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:16:43.567011Z",
     "end_time": "2025-11-25T11:16:43.586965Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new GraphCypherQAChain chain...\u001B[0m\n",
      "Generated Cypher:\n",
      "\u001B[32;1m\u001B[1;3mcypher\n",
      "MATCH (:Name {name: '乙肝'})-[:治疗药物]->(drug:drug)\n",
      "RETURN drug.name\n",
      "\u001B[0m\n",
      "Full Context:\n",
      "\u001B[32;1m\u001B[1;3m[{'drug.name': '注射用盐酸精氨...'}, {'drug.name': '碧云砂乙肝颗粒'}, {'drug.name': '恩替卡韦分散片'}]\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'query': '乙肝应该吃什么药', 'result': '乙肝患者可以考虑使用以下药物：注射用盐酸精氨酸、碧云砂乙肝颗粒和恩替卡韦分散片。'}\n"
     ]
    }
   ],
   "source": [
    "question = \"乙肝应该吃什么药\"\n",
    "r=chain.invoke({\"query\": question})\n",
    "print(r)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:17:15.843606Z",
     "end_time": "2025-11-25T11:17:22.744859Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new GraphCypherQAChain chain...\u001B[0m\n",
      "Generated Cypher:\n",
      "\u001B[32;1m\u001B[1;3mcypher\n",
      "MATCH (n:Name)-[:症状]->(s:symptom {name: '头疼'}), (n)-[:治疗药物]->(d:drug)\n",
      "RETURN d.name\n",
      "\u001B[0m\n",
      "Full Context:\n",
      "\u001B[32;1m\u001B[1;3m[{'d.name': '颈复康颗粒'}, {'d.name': '颈腰康胶囊'}, {'d.name': '消痛贴膏'}, {'d.name': '艾附暖宫丸'}, {'d.name': '加味益母草膏'}, {'d.name': '定坤丹'}]\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'query': '我的症状是头疼，应该吃什么药', 'result': '针对头疼症状，可以考虑以下药物：颈复康颗粒、颈腰康胶囊或消痛贴膏。但具体用药还需根据医生建议和个人情况决定。'}\n"
     ]
    }
   ],
   "source": [
    "question = \"我的症状是头疼，应该吃什么药\"\n",
    "r=chain.invoke({\"query\": question})\n",
    "print(r)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:17:22.743823Z",
     "end_time": "2025-11-25T11:17:28.205959Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new GraphCypherQAChain chain...\u001B[0m\n",
      "Generated Cypher:\n",
      "\u001B[32;1m\u001B[1;3mcypher\n",
      "MATCH (:drug {name: '颈复康颗粒'})<-[:治疗药物]-(disease:Name)\n",
      "RETURN disease.name\n",
      "\u001B[0m\n",
      "Full Context:\n",
      "\u001B[32;1m\u001B[1;3m[{'disease.name': '颈椎病'}]\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'query': '颈复康颗粒这个药能够治疗什么病', 'result': '颈复康颗粒主要用于治疗颈椎病。'}\n"
     ]
    }
   ],
   "source": [
    "question = \"颈复康颗粒这个药能够治疗什么病\"\n",
    "r=chain.invoke({\"query\": question})\n",
    "print(r)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:19:01.337842Z",
     "end_time": "2025-11-25T11:19:05.869020Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new GraphCypherQAChain chain...\u001B[0m\n",
      "Generated Cypher:\n",
      "\u001B[32;1m\u001B[1;3mMATCH (d:drug {name: '颈复康颗粒'})<-[:治疗药物]-(n:Name)-[:症状]->(s:symptom)\n",
      "RETURN s.name\u001B[0m\n",
      "Full Context:\n",
      "\u001B[32;1m\u001B[1;3m[{'s.name': '头疼'}, {'s.name': '颈部僵硬'}, {'s.name': '头颈部活动受限'}, {'s.name': '颈椎痛'}, {'s.name': '肩背痛'}, {'s.name': '上肢麻痹'}]\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'query': '颈复康颗粒这个药能够缓解什么症状（你可以先查询能够治疗什么病，再查询能够治疗什么症状）', 'result': '颈复康颗粒能够缓解以下症状：头疼、颈部僵硬、头颈部活动受限、颈椎痛、肩背痛以及上肢麻痹。'}\n"
     ]
    }
   ],
   "source": [
    "question = \"颈复康颗粒这个药能够缓解什么症状（你可以先查询能够治疗什么病，再查询能够治疗什么症状）\"\n",
    "r=chain.invoke({\"query\": question})\n",
    "print(r)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T11:20:06.563627Z",
     "end_time": "2025-11-25T11:20:10.636161Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "'''\n",
    "如何提升？搭建agent，第一个llm用于分类，匹配用户的问题具体类型，第二个llm用于生成cyper语句\n",
    "'''"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MATCH (d:disease {name: '乙肝'})-[:is_drug]->(drug:drug) RETURN drug.name\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "接入tugraph，导出schema，然后接入llm，生成cypher语句,先调试好提示词生成cypher，然后到机房跑一下\n",
    "'''\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "import json, textwrap\n",
    "\n",
    "# 1. 读文件\n",
    "with open('data/apikey.txt', 'r', encoding='utf-8') as file:\n",
    "    api_key = file.read()\n",
    "\n",
    "with open('data/default_schema.json', 'r', encoding='utf-8') as f:\n",
    "    schema = json.load(f)\n",
    "\n",
    "# 2. 转成紧凑字符串（节省 token）\n",
    "schema_str = json.dumps(schema, ensure_ascii=False, separators=(',', ':'))\n",
    "\n",
    "# 3. 拼 prompt\n",
    "user = '乙肝（疾病）吃什么药'\n",
    "prompt = \"\"\"\n",
    "现在你是一个数仓管理员，我会给你tugraph的schema，也会给你用户问题，你需要根据用户问题生成cypher语句查询。\n",
    "要求：只返回cypher语句，其他都不返回。\n",
    "schema:{schema}\n",
    "\"\"\"\n",
    "\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "model=\"deepseek-ai/DeepSeek-V3\",\n",
    "temperature=0,\n",
    "openai_api_key=api_key,\n",
    "openai_api_base=\"https://api.siliconflow.cn/v1\"\n",
    ")\n",
    "\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\",prompt,),\n",
    "        (\"user\", \"问题：{input}\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "chain = prompt | llm\n",
    "\n",
    "ai_msg =chain.invoke(\n",
    "   {\n",
    "       \"input\": user,\n",
    "       \"schema\":schema\n",
    "   }\n",
    ")\n",
    "\n",
    "print(ai_msg.content)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-26T15:41:52.562449Z",
     "end_time": "2025-11-26T15:41:54.955050Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new GraphCypherQAChain chain...\u001B[0m\n",
      "Generated Cypher:\n",
      "\u001B[32;1m\u001B[1;3mcypher\n",
      "MATCH (:drug {name: '颈复康颗粒'})<-[:治疗药物]-(disease:Name)\n",
      "RETURN disease.name\n",
      "\u001B[0m\n",
      "Full Context:\n",
      "\u001B[32;1m\u001B[1;3m[{'disease.name': '颈椎病'}]\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'query': '颈复康颗粒这个药能够治疗什么病', 'result': '颈复康颗粒主要用于治疗颈椎病。'}\n"
     ]
    }
   ],
   "source": [
    "question = \"颈复康颗粒这个药能够治疗什么病\"\n",
    "r=chain.invoke({\"query\": question})\n",
    "print(r)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-11-25T12:32:40.537250Z",
     "end_time": "2025-11-25T12:32:43.720527Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
